document.addEventListener('DOMContentLoaded', () => {
  ;({
    el: {
      concentration: document.getElementById('js-concentration'),
      btnStart: document.getElementById('js-btnStart'),
      btnBack: document.getElementById('js-btnBack'),
      btnPause: document.getElementById('js-btnPause'),
      btnReStart: document.getElementById('js-btnReStart'),
      countDown: document.getElementById('js-countDown'),
      timer: document.getElementById('js-timer'),
      number: document.getElementById('js-number'),
      cards: document.getElementById('js-cards'),
      cardsNumber: document.getElementById('js-cardsNumber'),
      overlay: document.getElementById('js-overlay'),
    },

    data: {
      cardsArray: [],
      cardsLen: 0,
      timerCount: 0,
      timerID: 0,
    },

    util: {
      // 配列をランダムに並び替え
      shuffleArray(array) {
        for (let i = array.length - 1; i >= 0; i--) {
          let rand = Math.floor(Math.random() * (i + 1))
          ;[array[i], array[rand]] = [array[rand], array[i]]
        }
      },
    },

    init() {
      const self = this
      self.cards().createCards()
      self.event().init()
    },

    event() {
      const self = this
      const el = self.el
      return {
        init() {
          this.clickBtnStart()
          this.clickBtnBack()
          this.clickBtnPause()
          this.clickBtnReStart()
          this.clickOverlay()
        },
        // スタートボタンをクリック
        clickBtnStart() {
          el.btnStart.addEventListener('click', () => {
            self.game().start()
          })
        },
        // バックボタンをクリック
        clickBtnBack() {
          el.btnBack.addEventListener('click', () => {
            self.game().end()
          })
        },
        // ポーズボタンをクリック
        clickBtnPause() {
          el.btnPause.addEventListener('click', () => {
            self.game().pause()
          })
        },
        // リスタートボタンをクリック
        clickBtnReStart() {
          el.btnReStart.addEventListener('click', () => {
            self.game().start()
          })
        },
        // オーバレイをクリック
        clickOverlay() {
          el.overlay.addEventListener('click', () => {
            self.game().breakPause()
          })
        },
      }
    },

    cards() {
      const self = this
      const el = self.el
      const data = self.data
      const util = self.util
      return {
        // カードの配列を作成してランダムに並び替え
        createCards() {
          const marksArray = ['club', 'diamond', 'heart', 'spade']
          const marksLen = marksArray.length
          const SUIT_LEN = 13
          for (let i = 0; i < marksLen; i++) {
            for (let j = 1; j <= SUIT_LEN; j++) {
              data.cardsArray.push({
                mark: marksArray[i],
                num: j,
              })
            }
          }
          util.shuffleArray(data.cardsArray)
        },

        // カード枚数を変更
        filterCards() {
          let array = []
          let len = el.cardsNumber.value / 2
          for (let i = 0; i < len; i++) {
            for (let j = i + 1, len = data.cardsArray.length; j < len; j++) {
              if (data.cardsArray[i].num === data.cardsArray[j].num) {
                array.push(
                  {
                    mark: data.cardsArray[i].mark,
                    num: data.cardsArray[i].num,
                  },
                  {
                    mark: data.cardsArray[j].mark,
                    num: data.cardsArray[j].num,
                  },
                )
                break
              }
            }
          }
          util.shuffleArray(array)
          return array
        },

        // カードの配列からDOM要素を作成して挿入
        appendCards() {
          const fragment = document.createDocumentFragment()
          let array
          // カード枚数が52枚
          if (Number(el.cardsNumber.value) === data.cardsArray.length) {
            array = data.cardsArray
          }
          // カード枚数が52枚以外
          else {
            array = self.cards().filterCards()
          }
          data.cardsLen = array.length
          for (let i = 0; i < data.cardsLen; i++) {
            let card = document.createElement('li')
            card.className = 'cards_item'
            card.dataset.mark = array[i].mark
            card.dataset.num = array[i].num
            fragment.appendChild(card)
          }
          el.cards.appendChild(fragment)
        },

        // カードを消去
        removeCards() {
          while (el.cards.firstChild) {
            el.cards.removeChild(el.cards.firstChild)
          }
        },
      }
    },

    game() {
      const self = this
      const el = self.el
      const data = self.data
      const util = self.util
      let selectArray = []
      return {
        start() {
          // プレイ済みだったら
          if (data.timerID) {
            util.shuffleArray(data.cardsArray)
            self.cards().removeCards()
            self.game().timer.clear()
            el.concentration.classList.remove('is-finish')
          }
          self.cards().appendCards()
          self.game().select()
          self.game().countDown()
          el.concentration.classList.add('is-play', 'is-countdown')
          el.number.textContent = `0/${data.cardsLen}`
        },
        countDown() {
          const COUNT_DOWN_NUM = 3
          const countDownTimer = setInterval(() => {
            let num = Number(el.countDown.textContent)
            switch (num) {
              case 3:
              case 2:
                el.countDown.textContent = num - 1
                el.countDown.classList.remove(`is-${num}`)
                el.countDown.classList.add(`is-${num - 1}`)
                break
              case 1:
                el.countDown.textContent = `GO!`
                el.countDown.classList.remove(`is-${num}`)
                el.countDown.classList.add(`is-go`)
                break
              default:
                clearInterval(countDownTimer)
                self.game().timer.start()
                el.concentration.classList.remove('is-countdown')
                el.countDown.textContent = COUNT_DOWN_NUM
                el.countDown.classList.remove(`is-go`)
            }
          }, 1000)
          el.countDown.textContent = COUNT_DOWN_NUM
        },
        pause() {
          self.game().timer.stop()
          el.concentration.classList.add('is-pause')
        },
        breakPause() {
          if (el.concentration.classList.contains('is-pause')) {
            self.game().timer.start()
            el.concentration.classList.remove('is-pause')
          }
        },
        end() {
          self.cards().removeCards()
          self.game().timer.clear()
          el.concentration.classList.remove('is-play')
        },
        select() {
          const cards = el.cards.querySelectorAll('.cards_item')
          for (let i = 0, len = cards.length; i < len; i++) {
            cards[i].addEventListener('click', () => {
              const selectObj = {
                mark: cards[i].dataset.mark,
                num: cards[i].dataset.num,
              }
              // 1枚目を選択
              if (selectArray.length === 0) {
                // 既に開いているカードがあったら閉じる
                for (let j = 0, len = cards.length; j < len; j++) {
                  if (cards[j].classList.contains('is-open')) {
                    cards[j].classList.remove('is-open')
                  }
                }
                cards[i].classList.add('is-open')
                selectArray.push(selectObj)
              }
              // 2枚目を選択
              else if (selectArray.length === 1) {
                cards[i].classList.add('is-open')
                selectArray.push(selectObj)
                selectArray = self.game().judge(selectArray)
              }
            })
          }
        },
        judge(array) {
          const openCards = el.cards.querySelectorAll('.is-open')
          let isSame = false
          for (let i = 0, len = openCards.length; i < len; i++) {
            // 正解だったらフラグをtrue
            if (array[0].num === array[1].num) {
              isSame = true
            }
            setTimeout(() => {
              // 正解
              if (isSame) {
                let hidesLen
                openCards[i].classList.add('is-hide')
                openCards[i].classList.remove('is-open')
                hidesLen = el.cards.querySelectorAll('.is-hide').length
                el.number.textContent = `${hidesLen}/${data.cardsLen}`
                // 残りのカードがない
                if (data.cardsLen === hidesLen) {
                  self.game().timer.stop()
                  el.concentration.classList.add('is-finish')
                }
              }
              // 不正解
              else {
                openCards[i].classList.remove('is-open')
              }
            }, 1000)
          }
          return []
        },
        timer: {
          start() {
            data.timerID = setInterval(() => {
              data.timerCount++
              let min = Math.floor(data.timerCount / 100 / 60)
              let sec = Math.floor(data.timerCount / 100)
              let msec = data.timerCount % 100
              min = `0${min}`.slice(-2)
              // 秒が60秒以上の場合　例）89秒→29秒にする
              sec = sec >= 60 ? sec % 60 : sec
              sec = `0${sec}`.slice(-2)
              msec = `0${msec}`.slice(-2)
              self.el.timer.textContent = `${min}:${sec}:${msec}`
            }, 10)
          },
          stop() {
            clearInterval(data.timerID)
          },
          clear() {
            data.timerCount = 0
            self.el.timer.textContent = `00:00:00`
            clearInterval(data.timerID)
          },
        },
      }
    },
  }.init())
})